New upstream version 0.1.38
authorJeremy Bicha <jbicha@debian.org>
Wed, 22 Nov 2017 14:53:25 +0000 (09:53 -0500)
committerJeremy Bicha <jbicha@debian.org>
Wed, 22 Nov 2017 14:53:25 +0000 (09:53 -0500)
24 files changed:
INSTALL
NEWS
README
babl/babl-cache.c
babl/babl-conversion.c
babl/babl-format.c
babl/babl-icc.c
babl/babl-internal.c
babl/babl-memory.c
babl/babl-palette.c
babl/babl-space.c
babl/babl-trc.c
babl/babl-util.c
babl/babl-version.h
babl/babl.h
babl/base/pow-24.c
babl/base/pow-24.h
configure
configure.ac
export-symbols
extensions/CIE.c
extensions/gggl-lies.c
extensions/gggl.c
extensions/sse2-float.c

diff --git a/INSTALL b/INSTALL
index ea3004fd4ff8ef5f9aff0c24d19e19cb5c8902b9..d2dc506e156d93cc3bafeae0123dde9c622608c3 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,5 +1,5 @@
 
-babl 0.1.34
+babl 0.1.38
 
     Dynamic; any to any, pixel format conversion library.
 
@@ -12,10 +12,10 @@ From a released version the following is the expected method of
 installation (or a variation on this theme):
 
      ------------------------------------------------------------
-     foo$ wget ftp://ftp.gtk.org/pub/babl/0.1/babl-0.1.34.tar.bz2
-     foo$ tar jxf babl-0.1.34.tar.gz
-     foo$ cd babl-0.1.34
-     foo/babl-0.1.34$ ./configure && make && sudo make install
+     foo$ wget ftp://ftp.gtk.org/pub/babl/0.1/babl-0.1.38.tar.bz2
+     foo$ tar jxf babl-0.1.38.tar.gz
+     foo$ cd babl-0.1.38
+     foo/babl-0.1.38$ ./configure && make && sudo make install
      ------------------------------------------------------------
 
 
diff --git a/NEWS b/NEWS
index c50a4eff7077441f1526a265a8c615f344dbf5f8..fba23b6159adde11385bbf8af2b63e559c55c45a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,9 +1,17 @@
                                                                  <dl><dt><!--
 The NEWS file in the babl source tree is the source location for
 the news section both in the README and the webpage.
-
-
                                                                           -->
+
+2017-11-15 babl-0.1.38                                              </dt><dd>
+Added format "CIE L float", a couple of protections against division by 0.0
+                                                                    </dd><dt>
+2017-11-10 babl-0.1.36                                              </dt><dd>
+Optimized customized primary aware code paths for CIE Lab<->RGB conversions,
+improved accuracy of gamma approximations. New API babl_format_exists() for
+checking validity of babl format name, crash proofing of cache handling and use
+of environment variables.
+                                                                    </dd><dt>
 2017-10-06 babl-0.1.34                                              </dt><dd>
 Brown paper bag release, Fix indexed / custom primaries conflict, and re-export
 a symbol used by old GEGL/GIMPs.
diff --git a/README b/README
index 6472d36e368ac26f938227cbb458634a9e6926e7..d213b53da8e98b59233f8274cf5768dcc159bfc4 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Babl-0.1.34
+Babl-0.1.38
 
 Contents
 
@@ -64,6 +64,14 @@ babl release. If there are significant improvements to babl when a GEGL
 release is done a babl release is most often put out just prior to the
 GEGL release.
 
+2017-11-15 babl-0.1.38
+    Added format "CIE L float", a couple of protections against
+    division by 0.0
+2017-11-10 babl-0.1.36
+    Optimized customized primary aware code paths for CIE Lab<->RGB
+    conversions, improved accuracy of gamma approximations. New API
+    babl_format_exists() for checking validity of babl format name,
+    crash proofing of cache handling and use of environment variables.
 2017-10-06 babl-0.1.34
     Brown paper bag release, Fix indexed / custom primaries conflict,
     and re-export a symbol used by old GEGL/GIMPs.
@@ -1691,6 +1699,16 @@ components
     float CIE b
     float A
 
+CIE L float
+
+bytes/pixel
+    4
+model
+    CIE Lab
+components
+
+    float CIE L
+
 CIE L alpha float
 
 bytes/pixel
@@ -2186,4 +2204,4 @@ Massimo Valentini
 Ell
     fast paths
 
-/babl-0.1.34
+/babl-0.1.38
index fa3f3879acd99eea123305f3f58395e6953bb47d..dcc76f4064899df0b6f5182e1bd08ff773d324ed 100644 (file)
@@ -37,6 +37,7 @@ mk_ancestry_iter (const char *path)
 {
   char copy[4096];
   strncpy (copy, path, 4096);
+  copy[sizeof (copy) - 1] = '\0';
   if (strrchr (copy, '/'))
     {
       *strrchr (copy, '/') = '\0';
@@ -63,6 +64,7 @@ mk_ancestry (const char *path)
 {
   char copy[4096];
   strncpy (copy, path, 4096);
+  copy[sizeof (copy) - 1] = '\0';
 #ifdef _WIN32
   for (char *c = copy; *c; c++)
     if (*c == '\\')
@@ -77,18 +79,19 @@ static const char *fish_cache_path (void)
   static char path[4096];
 
   strncpy (path, FALLBACK_CACHE_PATH, 4096);
+  path[sizeof (path) - 1] = '\0';
 #ifndef _WIN32
   if (getenv ("XDG_CACHE_HOME"))
-    sprintf (path, "%s/babl/babl-fishes", getenv("XDG_CACHE_HOME"));
+    snprintf (path, sizeof (path), "%s/babl/babl-fishes", getenv("XDG_CACHE_HOME"));
   else if (getenv ("HOME"))
-    sprintf (path, "%s/.cache/babl/babl-fishes", getenv("HOME"));
+    snprintf (path, sizeof (path), "%s/.cache/babl/babl-fishes", getenv("HOME"));
 #else
 {
   char win32path[4096];
   if (SHGetFolderPathA (NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, win32path) == S_OK)
-    sprintf (path, "%s\\%s\\babl-fishes.txt", win32path, BABL_LIBRARY);
+    snprintf (path, sizeof (path), "%s\\%s\\babl-fishes.txt", win32path, BABL_LIBRARY);
   else if (getenv ("TEMP"))
-    sprintf (path, "%s\\babl-fishes.txt", getenv("TEMP"));
+    snprintf (path, sizeof (path), "%s\\babl-fishes.txt", getenv("TEMP"));
 }
 #endif
 
@@ -150,13 +153,13 @@ static const char *cache_header (void)
 {
   static char buf[2048];
   if (strchr (BABL_GIT_VERSION, ' ')) // we must be building from tarball
-    sprintf (buf, "#%i.%i.%i BABL_PATH_LENGTH=%d BABL_TOLERANCE=%f",
+    snprintf (buf, sizeof (buf),
+             "#%i.%i.%i BABL_PATH_LENGTH=%d BABL_TOLERANCE=%f",
              BABL_MAJOR_VERSION, BABL_MINOR_VERSION, BABL_MICRO_VERSION,
              _babl_max_path_len (), _babl_legal_error ());
   else
-    sprintf (buf, "#%s BABL_PATH_LENGTH=%d BABL_TOLERANCE=%f",
-             BABL_GIT_VERSION,
-             _babl_max_path_len (), _babl_legal_error ());
+    snprintf (buf, sizeof (buf), "#%s BABL_PATH_LENGTH=%d BABL_TOLERANCE=%f",
+             BABL_GIT_VERSION, _babl_max_path_len (), _babl_legal_error ());
   return buf;
 }
 
@@ -167,10 +170,15 @@ void babl_store_db (void)
   char *tmpp = calloc(8000,1);
   FILE *dbfile;
 
-  sprintf (tmpp, "%s~", fish_cache_path ());
+  if (!tmpp)
+    return;
+  snprintf (tmpp, 8000, "%s~", fish_cache_path ());
   dbfile  = fopen (tmpp, "w");
   if (!dbfile)
+  {
+    free (tmpp);
     return;
+  }
   fprintf (dbfile, "%s\n", cache_header ());
 
   /* sort the list of fishes by usage, making next run more efficient -
@@ -270,6 +278,7 @@ void babl_init_db (void)
             {
               fprintf (stderr, "%s:%i: loading of cache failed\n",
                               __FUNCTION__, __LINE__);
+              free (contents);
               return;
             }
 
@@ -312,6 +321,7 @@ void babl_init_db (void)
             Babl *conv = (void*)babl_db_find(babl_conversion_db(), &token[1]);
             if (!conv)
             {
+              free (contents);
               return;
             }
             else
index 75e5c93b1472dbc4d21f0f7fa5bb82aaae849f1f..17dccf862aba6bacf3b041806fb85b2b1a5751b9 100644 (file)
@@ -154,7 +154,7 @@ create_name (Babl *source, Babl *destination, int type)
 {
   if (babl_extender ())
     {
-      snprintf (buf, 512 - 1, "%s %i: %s%s to %s",
+      snprintf (buf, sizeof (buf), "%s %i: %s%s to %s",
                 BABL (babl_extender ())->instance.name,
                 collisions,
                 type == BABL_CONVERSION_LINEAR ? "" :
@@ -162,18 +162,16 @@ create_name (Babl *source, Babl *destination, int type)
                 type == BABL_CONVERSION_PLANAR ? "planar " : "Eeeek! ",
                 source->instance.name,
                 destination->instance.name);
-      buf[511] = '\0';
     }
   else
     {
-      snprintf (buf, 512 - 1, "%s %s to %s %i",
+      snprintf (buf, sizeof (buf), "%s %s to %s %i",
                 type == BABL_CONVERSION_LINEAR ? "" :
                 type == BABL_CONVERSION_PLANE ? "plane " :
                 type == BABL_CONVERSION_PLANAR ? "planar " : "Eeeek! ",
                 source->instance.name,
                 destination->instance.name,
                 collisions);
-      buf[511] = '\0';
     }
   return buf;
 }
index 4ed14d0ef455ea88110295a5ae0b30ca2d3f0a5f..45c62b26e817e2d2691522446825d1ffa5f1ca6d 100644 (file)
@@ -135,8 +135,8 @@ format_new_from_format_with_space (const Babl *format, const Babl *space)
 {
   Babl *ret;
   char new_name[256];
-  sprintf (new_name, "%s-%s", babl_get_name ((void*)format),
-                              babl_get_name ((void*)space));
+  snprintf (new_name, sizeof (new_name), "%s-%s", babl_get_name ((void*)format),
+                                                  babl_get_name ((void*)space));
   ret = babl_db_find (babl_format_db(), new_name);
   if (ret)
     return ret;
@@ -161,6 +161,7 @@ create_name (const BablModel *model,
 {
   char            buf[512] = "";
   char           *p = &buf[0];
+  ssize_t         left;
   int             i;
   int             same_types = 1;
   const BablType**t          = type;
@@ -168,9 +169,11 @@ create_name (const BablModel *model,
   BablComponent **c1         = component;
   BablComponent **c2         = model->component;
 
-
-  sprintf (p, "%s ", model->instance.name);
+  left = 512;
+  snprintf (p, left, "%s ", model->instance.name);
   p += strlen (model->instance.name) + 1;
+  left -= strlen (model->instance.name) + 1;
+  babl_assert (left >= 0);
 
   i = components;
   while (i--)
@@ -202,7 +205,7 @@ create_name (const BablModel *model,
 
   if (same_types)
     {
-      sprintf (p, "%s", first_type->instance.name);
+      snprintf (p, left, "%s", first_type->instance.name);
       return babl_strdup (buf);
     }
 
@@ -210,11 +213,14 @@ create_name (const BablModel *model,
 
   while (i--)
     {
-      sprintf (p, "(%s as %s) ",
+      snprintf (p, left, "(%s as %s) ",
                (*component)->instance.name,
                (*type)->instance.name);
       p += strlen ((*component)->instance.name) +
            strlen ((*type)->instance.name) + strlen ("( as ) ");
+      left -= strlen ((*component)->instance.name) +
+              strlen ((*type)->instance.name) + strlen ("( as ) ");
+      babl_assert (left >= 0);
       component++;
       type++;
     }
@@ -226,7 +232,7 @@ ncomponents_create_name (const Babl *type,
                          int         components)
 {
   char buf[512];
-  sprintf (buf, "%s[%i] ", type->instance.name, components);
+  snprintf (buf, sizeof (buf), "%s[%i] ", type->instance.name, components);
   return babl_strdup (buf);
 }
 
@@ -742,4 +748,13 @@ babl_format_with_space (const char *name, const Babl *space)
   return ret;
 }
 
+int
+babl_format_exists (const char *name)
+{
+  if (babl_db_exist_by_name (db, name))
+    return 1;
+  return 0;
+}
+
+
 
index 45ba8fa4f1b7bd3bc4b1a03a485adf0f70b3bd7f..20841b9483125cc8da8c5f62c25124ab80cf5c0d 100644 (file)
@@ -973,7 +973,7 @@ char *babl_icc_get_key (const char *icc_data,
   {
     char tag[5];
     int val = icc_read (u32, 64);
-    sprintf (tag, "%i", val);
+    snprintf (tag, sizeof (tag), "%i", val);
     return strdup (tag);
   } else if (!strcmp (key, "tags"))
   {
index 0589e3f383badcadeb57fc70b9949568703687dc..e0b4f7a687fc8b9c4f0cd380a6f99fd577b37844 100644 (file)
@@ -65,7 +65,7 @@ babl_backtrack (void)
 {
   char buf[512];
 
-  sprintf (buf, "echo bt>/tmp/babl.gdb;"
+  snprintf (buf, sizeof (buf), "echo bt>/tmp/babl.gdb;"
            "gdb -q --batch -x /tmp/babl.gdb --pid=%i | grep 'in ''babl_die' -A40", getpid ());
   return system (buf);
 }
index d9e4d2fd692e3559682824db9235d986aac5e361..d0229e4d4aba6ac73693e845da0db5539f7e1dc7 100644 (file)
@@ -71,7 +71,7 @@ mem_stats (void)
 {
   static char buf[128];
 
-  sprintf (buf, "mallocs:%i callocs:%i strdups:%i dups:%i allocs:%i frees:%i reallocs:%i\t|",
+  snprintf (buf, sizeof (buf), "mallocs:%i callocs:%i strdups:%i dups:%i allocs:%i frees:%i reallocs:%i\t|",
            mallocs, callocs, strdups, dups, mallocs + callocs + strdups + dups, frees, reallocs);
   return buf;
 }
index 823ff0c3421c6ae68d41404188786976f067b544..fda96ae1f638e21799db861810e6f4f5bd788164 100644 (file)
@@ -483,7 +483,7 @@ const Babl *babl_new_palette (const char  *name,
   if (!name)
     {
       static int cnt = 0;
-      sprintf (cname, "_babl-int-%i", cnt++);
+      snprintf (cname, sizeof (cname), "_babl-int-%i", cnt++);
       name = cname;
     }
   else
index adc9e7a92c5a8612dc977699784b779dfe743ad4..781e41997461e17875320ab45953007a7dbc3ee0 100644 (file)
@@ -285,9 +285,9 @@ babl_space_from_rgbxyz_matrix (const char *name,
   space_db[i]=space;
   space_db[i].instance.name = space_db[i].name;
   if (name)
-    sprintf (space_db[i].name, "%s", name);
+    snprintf (space_db[i].name, sizeof (space_db[i].name), "%s", name);
   else
-    sprintf (space_db[i].name, "space-%.4f,%.4f_%.4f,%.4f_%.4f_%.4f,%.4f_%.4f,%.4f_%s,%s,%s",
+    snprintf (space_db[i].name, sizeof (space_db[i].name), "space-%.4f,%.4f_%.4f,%.4f_%.4f_%.4f,%.4f_%.4f,%.4f_%s,%s,%s",
                        rx, gx, bx,
                        ry, gy, by,
                        rz, gz, bz,
@@ -348,10 +348,11 @@ babl_space_from_chromaticities (const char *name,
   space_db[i]=space;
   space_db[i].instance.name = space_db[i].name;
   if (name)
-    sprintf (space_db[i].name, "%s", name);
+    snprintf (space_db[i].name, sizeof (space_db[i].name), "%s", name);
   else
           /* XXX: this can get longer than 256bytes ! */
-    sprintf (space_db[i].name, "space-%.4f,%.4f_%.4f,%.4f_%.4f,%.4f_%.4f,%.4f_%s,%s,%s",
+    snprintf (space_db[i].name, sizeof (space_db[i].name),
+             "space-%.4f,%.4f_%.4f,%.4f_%.4f,%.4f_%.4f,%.4f_%s,%s,%s",
              wx,wy,rx,ry,bx,by,gx,gy,babl_get_name (space.trc[0]),
              babl_get_name(space.trc[1]), babl_get_name(space.trc[2]));
 
index 7524ef8c10961b9beda8ac293cb3b11c4dbf8da1..0a007109c9b2a64daa33deefb9b7740ff07a892a 100644 (file)
@@ -292,11 +292,11 @@ babl_trc_new (const char *name,
   trc_db[i]=trc;
   trc_db[i].instance.name = trc_db[i].name;
   if (name)
-    sprintf (trc_db[i].name, "%s", name);
+    snprintf (trc_db[i].name, sizeof (trc_db[i].name), "%s", name);
   else if (n_lut)
-    sprintf (trc_db[i].name, "lut-trc");
+    snprintf (trc_db[i].name, sizeof (trc_db[i].name), "lut-trc");
   else
-    sprintf (trc_db[i].name, "trc-%i-%f", type, gamma);
+    snprintf (trc_db[i].name, sizeof (trc_db[i].name), "trc-%i-%f", type, gamma);
 
   if (n_lut)
   {
@@ -430,7 +430,7 @@ babl_trc_formula_srgb (double g, double a, double b, double c, double d)
       fabs (c - (-3417))  < 0.01)
     return babl_trc ("sRGB");
 
-  sprintf (name, "%.6f %.6f %.4f %.4f %.4f", g, a, b, c, d);
+  snprintf (name, sizeof (name), "%.6f %.6f %.4f %.4f %.4f", g, a, b, c, d);
   for (i = 0; name[i]; i++)
     if (name[i] == ',') name[i] = '.';
   while (name[strlen(name)-1]=='0')
@@ -446,7 +446,7 @@ babl_trc_gamma (double gamma)
   if (fabs (gamma - 1.0) < 0.01)
      return babl_trc_new ("linear", BABL_TRC_LINEAR, 1.0, 0, NULL);
 
-  sprintf (name, "%.6f", gamma);
+  snprintf (name, sizeof (name), "%.6f", gamma);
   for (i = 0; name[i]; i++)
     if (name[i] == ',') name[i] = '.';
   while (name[strlen(name)-1]=='0')
index 23c1513f9760eaf76113944a46609cffe35d50de..60b695df1f90f189763bfc4e7b924763c688f7ec 100644 (file)
@@ -116,10 +116,18 @@ _babl_file_get_contents (const char  *path,
   if (!file)
     return -1;
 
-  fseek (file, 0, SEEK_END);
-  size = ftell (file);
+  if (fseek (file, 0, SEEK_END) == -1 || (size = ftell (file)) == -1)
+    {
+      fclose (file);
+      return -1;
+    }
   if (length) *length = size;
   rewind (file);
+  if ((size_t) size > SIZE_MAX - 8)
+    {
+      fclose (file);
+      return -1;
+    }
   buffer = calloc(size + 8, 1);
 
   if (!buffer)
index 4d1e2dad9445b91f06b61e30db4bc9634de53f23..ed4a665179d0b510fb0a0cde257114b3a89bb4d7 100644 (file)
@@ -34,7 +34,7 @@
 
 #define BABL_MAJOR_VERSION 0
 #define BABL_MINOR_VERSION 1
-#define BABL_MICRO_VERSION 34
+#define BABL_MICRO_VERSION 38
 
 /** Get the version information on the babl library */
 void   babl_get_version (int *major,
index 5e299a75be17530b47ff7d5837335e66acedd7f9..a45de428b3accc41fc70836b9492ccec5c9b077c 100644 (file)
@@ -156,6 +156,15 @@ char *babl_icc_get_key (const char *icc_data,
  */
 const Babl * babl_format            (const char *name);
 
+/**
+ * babl_format_exists:
+ *
+ * Returns 1 if the provided format name is known by babl or 0 if it is
+ * not. Can also be used to verify that specific extension formats are
+ * available (though this can also be inferred from the version of babl).
+ */
+int babl_format_exists              (const char *name);
+
 /**
  * babl_format_with_space:
  *
index dbc40715ce263bd6c78ac36aeaa2487624d20b43..4587bf14d2b4956fe5f29563a11661fd98404d57 100644 (file)
@@ -48,8 +48,13 @@ init_newton (double x, double exponent, double c0, double c1, double c2)
 double
 babl_pow_24 (double x)
 {
-  double y = init_newton (x, -1./5, 0.9953189663, 0.9594345146, 0.6742970332);
+  double y;
   int i;
+  if (x > 16.0) {
+    /* for large values, fall back to a slower but more accurate version */
+    return exp (log (x) * 2.4);
+  }
+  y = init_newton (x, -1./5, 0.9953189663, 0.9594345146, 0.6742970332);
   for (i = 0; i < 3; i++)
     y = (1.+1./5)*y - ((1./5)*x*(y*y))*((y*y)*(y*y));
   x *= y;
@@ -61,9 +66,14 @@ babl_pow_24 (double x)
 double
 babl_pow_1_24 (double x)
 {
-  double y = init_newton (x, -1./12, 0.9976800269, 0.9885126933, 0.5908575383);
+  double y;
   int i;
   double z;
+  if (x > 1024.0) {
+    /* for large values, fall back to a slower but more accurate version */
+    return exp (log (x) * (1.0 / 2.4));
+  }
+  y = init_newton (x, -1./12, 0.9976800269, 0.9885126933, 0.5908575383);
   x = sqrt (x);
   /* newton's method for x^(-1/6) */
   z = (1./6.) * x;
@@ -102,10 +112,15 @@ init_newtonf (float x, float exponent, float c0, float c1, float c2)
 float
 babl_pow_24f (float x)
 {
-  float y = init_newtonf (x, -1.f/5, 0.9953189663f, 0.9594345146f, 0.6742970332f);
+  float y;
   int i;
+  if (x > 16.0f) {
+    /* for large values, fall back to a slower but more accurate version */
+    return expf (logf (x) * 2.4f);
+  }
+  y = init_newtonf (x, -1.f/5, 0.9953189663f, 0.9594345146f, 0.6742970332f);
   for (i = 0; i < 3; i++)
-    y = (1.f+1.f/5)*y - ((1./5)*x*(y*y))*((y*y)*(y*y));
+    y = (1.f+1.f/5)*y - ((1.f/5)*x*(y*y))*((y*y)*(y*y));
   x *= y;
   return x*x*x;
 }
@@ -115,9 +130,14 @@ babl_pow_24f (float x)
 float
 babl_pow_1_24f (float x)
 {
-  float y = init_newtonf (x, -1.f/12, 0.9976800269f, 0.9885126933f, 0.5908575383f);
+  float y;
   int i;
   float z;
+  if (x > 1024.0f) {
+    /* for large values, fall back to a slower but more accurate version */
+    return expf (logf (x) * (1.0f / 2.4f));
+  }
+  y = init_newtonf (x, -1.f/12, 0.9976800269f, 0.9885126933f, 0.5908575383f);
   x = sqrtf (x);
   /* newton's method for x^(-1/6) */
   z = (1.f/6.f) * x;
index a55c02906ba8e01b25e44e41c506182031d55246..3ea6984d4706fdd60726c267e194aed3f37f821e 100644 (file)
@@ -54,8 +54,13 @@ init_newton (double x, double exponent, double c0, double c1, double c2)
 static inline double
 babl_pow_24 (double x)
 {
-  double y = init_newton (x, -1./5, 0.9953189663, 0.9594345146, 0.6742970332);
+  double y;
   int i;
+  if (x > 16.0) {
+    /* for large values, fall back to a slower but more accurate version */
+    return exp (log (x) * 2.4);
+  }
+  y = init_newton (x, -1./5, 0.9953189663, 0.9594345146, 0.6742970332);
   for (i = 0; i < 3; i++)
     y = (1.+1./5)*y - ((1./5)*x*(y*y))*((y*y)*(y*y));
   x *= y;
@@ -67,9 +72,14 @@ babl_pow_24 (double x)
 static inline double
 babl_pow_1_24 (double x)
 {
-  double y = init_newton (x, -1./12, 0.9976800269, 0.9885126933, 0.5908575383);
+  double y;
   int i;
   double z;
+  if (x > 1024.0) {
+    /* for large values, fall back to a slower but more accurate version */
+    return exp (log (x) * (1.0 / 2.4));
+  }
+  y = init_newton (x, -1./12, 0.9976800269, 0.9885126933, 0.5908575383);
   x = sqrt (x);
   /* newton's method for x^(-1/6) */
   z = (1./6.) * x;
@@ -133,10 +143,15 @@ init_newtonf (float x, float exponent, float c0, float c1, float c2)
 static inline float
 babl_pow_24f (float x)
 {
-  float y = init_newtonf (x, -1.f/5, 0.9953189663f, 0.9594345146f, 0.6742970332f);
+  float y;
   int i;
+  if (x > 16.0f) {
+    /* for large values, fall back to a slower but more accurate version */
+    return expf (logf (x) * 2.4f);
+  }
+  y = init_newtonf (x, -1.f/5, 0.9953189663f, 0.9594345146f, 0.6742970332f);
   for (i = 0; i < 3; i++)
-    y = (1.f+1.f/5)*y - ((1./5)*x*(y*y))*((y*y)*(y*y));
+    y = (1.f+1.f/5)*y - ((1.f/5)*x*(y*y))*((y*y)*(y*y));
   x *= y;
   return x*x*x;
 }
@@ -146,9 +161,14 @@ babl_pow_24f (float x)
 static inline float
 babl_pow_1_24f (float x)
 {
-  float y = init_newtonf (x, -1.f/12, 0.9976800269f, 0.9885126933f, 0.5908575383f);
+  float y;
   int i;
   float z;
+  if (x > 1024.0f) {
+    /* for large values, fall back to a slower but more accurate version */
+    return expf (logf (x) * (1.0f / 2.4f));
+  }
+  y = init_newtonf (x, -1.f/12, 0.9976800269f, 0.9885126933f, 0.5908575383f);
   x = sqrtf (x);
   /* newton's method for x^(-1/6) */
   z = (1.f/6.f) * x;
index c808fee5d27d70b95b6e1e53421c437c9aa811af..bd885c58e72bb216c420aa6199905b00664ace40 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for babl 0.1.34.
+# Generated by GNU Autoconf 2.69 for babl 0.1.38.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='babl'
 PACKAGE_TARNAME='babl'
-PACKAGE_VERSION='0.1.34'
-PACKAGE_STRING='babl 0.1.34'
+PACKAGE_VERSION='0.1.38'
+PACKAGE_STRING='babl 0.1.38'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1381,7 +1381,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures babl 0.1.34 to adapt to many kinds of systems.
+\`configure' configures babl 0.1.38 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1453,7 +1453,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of babl 0.1.34:";;
+     short | recursive ) echo "Configuration of babl 0.1.38:";;
    esac
   cat <<\_ACEOF
 
@@ -1573,7 +1573,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-babl configure 0.1.34
+babl configure 0.1.38
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1938,7 +1938,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by babl $as_me 0.1.34, which was
+It was created by babl $as_me 0.1.38, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2294,11 +2294,11 @@ ac_config_headers="$ac_config_headers config.h"
 
 BABL_MAJOR_VERSION=0
 BABL_MINOR_VERSION=1
-BABL_MICRO_VERSION=34
+BABL_MICRO_VERSION=38
 BABL_INTERFACE_AGE=1
-BABL_BINARY_AGE=134
-BABL_VERSION=0.1.34
-BABL_REAL_VERSION=0.1.34
+BABL_BINARY_AGE=138
+BABL_VERSION=0.1.38
+BABL_REAL_VERSION=0.1.38
 BABL_API_VERSION=0.1
 
 
@@ -2333,7 +2333,7 @@ fi
 
 
 
-BABL_LIBRARY_VERSION="133:1:133"
+BABL_LIBRARY_VERSION="137:1:137"
 BABL_CURRENT_MINUS_AGE=0
 
 
@@ -2965,7 +2965,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='babl'
- VERSION='0.1.34'
+ VERSION='0.1.38'
 
 
 # Some tools Automake needs.
@@ -14864,7 +14864,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by babl $as_me 0.1.34, which was
+This file was extended by babl $as_me 0.1.38, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -14930,7 +14930,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-babl config.status 0.1.34
+babl config.status 0.1.38
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index dda45b1fc8ad6885da6b3cac84443617115938ba..c1fd10f8bca45a81f5ffb88610c39adbffa90e53 100644 (file)
@@ -14,7 +14,7 @@ AC_PREREQ(2.54)
 
 m4_define([babl_major_version], [0])
 m4_define([babl_minor_version], [1])
-m4_define([babl_micro_version], [34])
+m4_define([babl_micro_version], [38])
 m4_define([babl_real_version],
           [babl_major_version.babl_minor_version.babl_micro_version])
 m4_define([babl_version], [babl_real_version])
index 2ba4bb826b5725caff627f45c0968dc086c03403..f85fec9e1ea9df5a5f9cddfabc3319e7df7113d1 100644 (file)
@@ -8,6 +8,7 @@ babl_exit
 babl_fast_fish
 babl_fish
 babl_format
+babl_format_exists
 babl_format_get_bytes_per_pixel
 babl_format_get_model
 babl_format_get_n_components
index d16d86256c3c8a8d8ff920f30e50f726d712d443..658fd2a8b304f2c2c9a6b87adaed18e47ccaa614 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 2005, 2014 Øyvind Kolås.
  * Copyright (C) 2009, Martin Nordholts
  * Copyright (C) 2014, Elle Stone
+ * Copyright (C) 2017, Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -168,13 +169,13 @@ XYZ_to_LAB (double X,
   double y_r = Y / D50_WHITE_REF_Y;
   double z_r = Z / D50_WHITE_REF_Z;
 
-  if (x_r > LAB_EPSILON) f_x = pow(x_r, 1.0 / 3.0);
+  if (x_r > LAB_EPSILON) f_x = cbrt(x_r);
   else ( f_x = ((LAB_KAPPA * x_r) + 16) / 116.0 );
 
-  if (y_r > LAB_EPSILON) f_y = pow(y_r, 1.0 / 3.0);
+  if (y_r > LAB_EPSILON) f_y = cbrt(y_r);
   else ( f_y = ((LAB_KAPPA * y_r) + 16) / 116.0 );
 
-  if (z_r > LAB_EPSILON) f_z = pow(z_r, 1.0 / 3.0);
+  if (z_r > LAB_EPSILON) f_z = cbrt(z_r);
   else ( f_z = ((LAB_KAPPA * z_r) + 16) / 116.0 );
 
   *to_L = (116.0 * f_y) - 16.0;
@@ -591,6 +592,44 @@ cubef (float f)
   return f * f * f;
 }
 
+static void
+Yf_to_Lf (const Babl *conversion,float *src,
+          float *dst,
+          long   samples)
+{
+  long n = samples;
+
+  while (n--)
+    {
+      float yr = src[0];
+      float L  = yr > LAB_EPSILON ? 116.0f * _cbrtf (yr) - 16 : LAB_KAPPA * yr;
+
+      dst[0] = L;
+
+      src++;
+      dst++;
+    }
+}
+
+static void
+Yaf_to_Lf (const Babl *conversion,float *src,
+           float *dst,
+           long   samples)
+{
+  long n = samples;
+
+  while (n--)
+    {
+      float yr = src[0];
+      float L  = yr > LAB_EPSILON ? 116.0f * _cbrtf (yr) - 16 : LAB_KAPPA * yr;
+
+      dst[0] = L;
+
+      src += 2;
+      dst += 1;
+    }
+}
+
 static void
 Yaf_to_Laf (const Babl *conversion,float *src,
             float *dst,
@@ -617,6 +656,16 @@ rgbf_to_Labf (const Babl *conversion,float *src,
               float *dst,
               long   samples)
 {
+  const Babl *space = babl_conversion_get_source_space (conversion);
+  float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_X;
+  float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_X;
+  float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_X;
+  float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Y;
+  float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Y;
+  float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Y;
+  float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Z;
+  float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Z;
+  float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Z;
   long n = samples;
 
   while (n--)
@@ -625,9 +674,9 @@ rgbf_to_Labf (const Babl *conversion,float *src,
       float g = src[1];
       float b = src[2];
 
-      float xr = 0.43603516f / D50_WHITE_REF_X * r + 0.38511658f / D50_WHITE_REF_X * g + 0.14305115f / D50_WHITE_REF_X * b;
-      float yr = 0.22248840f / D50_WHITE_REF_Y * r + 0.71690369f / D50_WHITE_REF_Y * g + 0.06060791f / D50_WHITE_REF_Y * b;
-      float zr = 0.01391602f / D50_WHITE_REF_Z * r + 0.09706116f / D50_WHITE_REF_Z * g + 0.71392822f / D50_WHITE_REF_Z * b;
+      float xr = m_0_0 * r + m_0_1 * g + m_0_2 * b;
+      float yr = m_1_0 * r + m_1_1 * g + m_1_2 * b;
+      float zr = m_2_0 * r + m_2_1 * g + m_2_2 * b;
 
       float fx = xr > LAB_EPSILON ? _cbrtf (xr) : (LAB_KAPPA * xr + 16.0f) / 116.0f;
       float fy = yr > LAB_EPSILON ? _cbrtf (yr) : (LAB_KAPPA * yr + 16.0f) / 116.0f;
@@ -646,11 +695,95 @@ rgbf_to_Labf (const Babl *conversion,float *src,
     }
 }
 
+static void
+rgbaf_to_Lf (const Babl *conversion,float *src,
+             float *dst,
+             long   samples)
+{
+  const Babl *space = babl_conversion_get_source_space (conversion);
+  float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Y;
+  float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Y;
+  float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Y;
+  long n = samples;
+
+  while (n--)
+    {
+      float r = src[0];
+      float g = src[1];
+      float b = src[2];
+
+      float yr = m_1_0 * r + m_1_1 * g + m_1_2 * b;
+
+      float fy = yr > LAB_EPSILON ? _cbrtf (yr) : (LAB_KAPPA * yr + 16.0f) / 116.0f;
+
+      float L = 116.0f * fy - 16.0f;
+
+      dst[0] = L;
+
+      src += 4;
+      dst += 1;
+    }
+}
+
+static void
+rgbaf_to_Labf (const Babl *conversion,float *src,
+               float *dst,
+               long   samples)
+{
+  const Babl *space = babl_conversion_get_source_space (conversion);
+  float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_X;
+  float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_X;
+  float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_X;
+  float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Y;
+  float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Y;
+  float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Y;
+  float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Z;
+  float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Z;
+  float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Z;
+  long n = samples;
+
+  while (n--)
+    {
+      float r = src[0];
+      float g = src[1];
+      float b = src[2];
+
+      float xr = m_0_0 * r + m_0_1 * g + m_0_2 * b;
+      float yr = m_1_0 * r + m_1_1 * g + m_1_2 * b;
+      float zr = m_2_0 * r + m_2_1 * g + m_2_2 * b;
+
+      float fx = xr > LAB_EPSILON ? _cbrtf (xr) : (LAB_KAPPA * xr + 16.0f) / 116.0f;
+      float fy = yr > LAB_EPSILON ? _cbrtf (yr) : (LAB_KAPPA * yr + 16.0f) / 116.0f;
+      float fz = zr > LAB_EPSILON ? _cbrtf (zr) : (LAB_KAPPA * zr + 16.0f) / 116.0f;
+
+      float L = 116.0f * fy - 16.0f;
+      float A = 500.0f * (fx - fy);
+      float B = 200.0f * (fy - fz);
+
+      dst[0] = L;
+      dst[1] = A;
+      dst[2] = B;
+
+      src += 4;
+      dst += 3;
+    }
+}
+
 static void
 rgbaf_to_Labaf (const Babl *conversion,float *src,
                 float *dst,
                 long   samples)
 {
+  const Babl *space = babl_conversion_get_source_space (conversion);
+  float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_X;
+  float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_X;
+  float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_X;
+  float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Y;
+  float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Y;
+  float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Y;
+  float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Z;
+  float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Z;
+  float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Z;
   long n = samples;
 
   while (n--)
@@ -660,9 +793,9 @@ rgbaf_to_Labaf (const Babl *conversion,float *src,
       float b = src[2];
       float a = src[3];
 
-      float xr = 0.43603516f / D50_WHITE_REF_X * r + 0.38511658f / D50_WHITE_REF_X * g + 0.14305115f / D50_WHITE_REF_X * b;
-      float yr = 0.22248840f / D50_WHITE_REF_Y * r + 0.71690369f / D50_WHITE_REF_Y * g + 0.06060791f / D50_WHITE_REF_Y * b;
-      float zr = 0.01391602f / D50_WHITE_REF_Z * r + 0.09706116f / D50_WHITE_REF_Z * g + 0.71392822f / D50_WHITE_REF_Z * b;
+      float xr = m_0_0 * r + m_0_1 * g + m_0_2 * b;
+      float yr = m_1_0 * r + m_1_1 * g + m_1_2 * b;
+      float zr = m_2_0 * r + m_2_1 * g + m_2_2 * b;
 
       float fx = xr > LAB_EPSILON ? _cbrtf (xr) : (LAB_KAPPA * xr + 16.0f) / 116.0f;
       float fy = yr > LAB_EPSILON ? _cbrtf (yr) : (LAB_KAPPA * yr + 16.0f) / 116.0f;
@@ -682,11 +815,53 @@ rgbaf_to_Labaf (const Babl *conversion,float *src,
     }
 }
 
+static void
+Labf_to_Lf (const Babl *conversion,float *src,
+            float *dst,
+            long   samples)
+{
+  long n = samples;
+
+  while (n--)
+    {
+      dst[0] = src[0];
+
+      src += 3;
+      dst += 1;
+    }
+}
+
+static void
+Labaf_to_Lf (const Babl *conversion,float *src,
+             float *dst,
+             long   samples)
+{
+  long n = samples;
+
+  while (n--)
+    {
+      dst[0] = src[0];
+
+      src += 4;
+      dst += 1;
+    }
+}
+
 static void
 Labf_to_rgbf (const Babl *conversion,float *src,
                 float *dst,
                 long   samples)
 {
+  const Babl *space = babl_conversion_get_source_space (conversion);
+  float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_X;
+  float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Y;
+  float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Z;
+  float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_X;
+  float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Y;
+  float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Z;
+  float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_X;
+  float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Y;
+  float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Z;
   long n = samples;
 
   while (n--)
@@ -703,9 +878,9 @@ Labf_to_rgbf (const Babl *conversion,float *src,
       float xr = cubef (fx) > LAB_EPSILON ? cubef (fx) : (fx * 116.0f - 16.0f) / LAB_KAPPA;
       float zr = cubef (fz) > LAB_EPSILON ? cubef (fz) : (fz * 116.0f - 16.0f) / LAB_KAPPA;
 
-      float r =  3.134274799724f * D50_WHITE_REF_X * xr -1.617275708956f * D50_WHITE_REF_Y * yr -0.490724283042f * D50_WHITE_REF_Z * zr;
-      float g = -0.978795575994f * D50_WHITE_REF_X * xr +1.916161689117f * D50_WHITE_REF_Y * yr +0.033453331711f * D50_WHITE_REF_Z * zr;
-      float b =  0.071976988401f * D50_WHITE_REF_X * xr -0.228984974402f * D50_WHITE_REF_Y * yr +1.405718224383f * D50_WHITE_REF_Z * zr;
+      float r = m_0_0 * xr + m_0_1 * yr + m_0_2 * zr;
+      float g = m_1_0 * xr + m_1_1 * yr + m_1_2 * zr;
+      float b = m_2_0 * xr + m_2_1 * yr + m_2_2 * zr;
 
       dst[0] = r;
       dst[1] = g;
@@ -721,6 +896,16 @@ Labaf_to_rgbaf (const Babl *conversion,float *src,
                 float *dst,
                 long   samples)
 {
+  const Babl *space = babl_conversion_get_source_space (conversion);
+  float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_X;
+  float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Y;
+  float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Z;
+  float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_X;
+  float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Y;
+  float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Z;
+  float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_X;
+  float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Y;
+  float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Z;
   long n = samples;
 
   while (n--)
@@ -738,9 +923,9 @@ Labaf_to_rgbaf (const Babl *conversion,float *src,
       float xr = cubef (fx) > LAB_EPSILON ? cubef (fx) : (fx * 116.0f - 16.0f) / LAB_KAPPA;
       float zr = cubef (fz) > LAB_EPSILON ? cubef (fz) : (fz * 116.0f - 16.0f) / LAB_KAPPA;
 
-      float r =  3.134274799724f * D50_WHITE_REF_X * xr -1.617275708956f * D50_WHITE_REF_Y * yr -0.490724283042f * D50_WHITE_REF_Z * zr;
-      float g = -0.978795575994f * D50_WHITE_REF_X * xr +1.916161689117f * D50_WHITE_REF_Y * yr +0.033453331711f * D50_WHITE_REF_Z * zr;
-      float b =  0.071976988401f * D50_WHITE_REF_X * xr -0.228984974402f * D50_WHITE_REF_Y * yr +1.405718224383f * D50_WHITE_REF_Z * zr;
+      float r = m_0_0 * xr + m_0_1 * yr + m_0_2 * zr;
+      float g = m_1_0 * xr + m_1_1 * yr + m_1_2 * zr;
+      float b = m_2_0 * xr + m_2_1 * yr + m_2_2 * zr;
 
       dst[0] = r;
       dst[1] = g;
@@ -903,6 +1088,12 @@ conversions (void)
     "linear", Labf_to_rgbf,
     NULL
   );
+  babl_conversion_new (
+    babl_format ("RGBA float"),
+    babl_format ("CIE Lab float"),
+    "linear", rgbaf_to_Labf,
+    NULL
+  );
   babl_conversion_new (
     babl_format ("RGBA float"),
     babl_format ("CIE Lab alpha float"),
@@ -915,12 +1106,42 @@ conversions (void)
     "linear", Labaf_to_rgbaf,
     NULL
   );
+  babl_conversion_new (
+    babl_format ("Y float"),
+    babl_format ("CIE L float"),
+    "linear", Yf_to_Lf,
+    NULL
+  );
+  babl_conversion_new (
+    babl_format ("YA float"),
+    babl_format ("CIE L float"),
+    "linear", Yaf_to_Lf,
+    NULL
+  );
   babl_conversion_new (
     babl_format ("YA float"),
     babl_format ("CIE L alpha float"),
     "linear", Yaf_to_Laf,
     NULL
   );
+  babl_conversion_new (
+    babl_format ("RGBA float"),
+    babl_format ("CIE L float"),
+    "linear", rgbaf_to_Lf,
+    NULL
+  );
+  babl_conversion_new (
+    babl_format ("CIE Lab float"),
+    babl_format ("CIE L float"),
+    "linear", Labf_to_Lf,
+    NULL
+  );
+  babl_conversion_new (
+    babl_format ("CIE Lab alpha float"),
+    babl_format ("CIE L float"),
+    "linear", Labaf_to_Lf,
+    NULL
+  );
   babl_conversion_new (
     babl_model ("RGBA"),
     babl_model ("CIE LCH(ab)"),
@@ -1019,6 +1240,13 @@ formats (void)
     babl_component ("A"),
     NULL);
 
+  babl_format_new (
+    "name", "CIE L float",
+    babl_model ("CIE Lab"),
+    babl_type ("float"),
+    babl_component ("CIE L"),
+    NULL);
+
   babl_format_new (
     "name", "CIE L alpha float",
     babl_model ("CIE Lab alpha"),
index b34f8ef81cec573a5aafe50042e7ed7bdd3117c9..c08dccd7cec0327d2ff38d9657ba6e084cce0f7d 100644 (file)
@@ -356,7 +356,10 @@ conv_gAF_gaF (const Babl *conversion,unsigned char *src, unsigned char *dst, lon
     {
       float alpha = (*(float *) (src + 4));
 
-      *(float *) dst = ((*(float *) src) / alpha);
+      if (alpha == 0.0f)
+        *(float *) dst = 0.0f;
+      else
+        *(float *) dst = ((*(float *) src) / alpha);
       dst           += 4;
       src           += 4;
       *(float *) dst = alpha;
index 83352d286e5bf813ca09fb086c4eb267769b211f..cf83988092a3b669645df4b570b83140d0c03940 100644 (file)
@@ -373,7 +373,10 @@ conv_gAF_gaF (const Babl *conversion,unsigned char *src, unsigned char *dst, lon
     {
       float alpha = (*(float *) (src + 4));
 
-      *(float *) dst = ((*(float *) src) / alpha);
+      if (alpha == 0.0f)
+        *(float *) dst = 0.0f;
+      else
+        *(float *) dst = ((*(float *) src) / alpha);
       dst           += 4;
       src           += 4;
       *(float *) dst = alpha;
@@ -557,10 +560,16 @@ conv_rgbA16_rgbaF (const Babl *conversion,unsigned char *src, unsigned char *dst
     {
       float alpha = (((unsigned short *) src)[3]) / 65535.0;
       int   c;
+      float recip_alpha;
+
+      if (alpha == 0.0f)
+        recip_alpha = 10000.0;
+      else
+        recip_alpha = 1.0/alpha;
 
       for (c = 0; c < 3; c++)
         {
-          (*(float *) dst) = (*(unsigned short *) src / 65535.0) alpha;
+          (*(float *) dst) = (*(unsigned short *) src / 65535.0) * recip_alpha;
           dst             += 4;
           src             += 2;
         }
index d26073c181dce5226113b0673df8e5b796dfdaa2..223f85ce085fbeb17417c65f4f68839eca75ed1f 100644 (file)
@@ -237,6 +237,22 @@ conv_rgbAF_linear_rgbaF_linear_spin (const Babl *conversion,const float *src, fl
 #define FLT_ONE 0x3f800000 // ((union {float f; int i;}){1.0f}).i
 #define FLT_MANTISSA (1<<23)
 
+static inline float
+sse_max_component (__v4sf x) {
+  __v4sf s;
+  __v4sf m;
+
+  /* m = [max (x[3], x[1]), max (x[2], x[0])] */
+  s = (__v4sf) _mm_shuffle_epi32 ((__m128i) x, _MM_SHUFFLE(0, 0, 3, 2));
+  m = _mm_max_ps (x, s);
+
+  /* m = [max (m[1], m[0])] = [max (max (x[3], x[1]), max (x[2], x[0]))] */
+  s = (__v4sf) _mm_shuffle_epi32 ((__m128i) m, _MM_SHUFFLE(0, 0, 0, 1));
+  m = _mm_max_ps (m, s);
+
+  return m[0];
+}
+
 static inline __v4sf
 sse_init_newton (__v4sf x, double exponent, double c0, double c1, double c2)
 {
@@ -249,6 +265,13 @@ static inline __v4sf
 sse_pow_1_24 (__v4sf x)
 {
   __v4sf y, z;
+  if (sse_max_component (x) > 1024.0f) {
+    /* for large values, fall back to a slower but more accurate version */
+    return _mm_set_ps (expf (logf (x[3]) * (1.0f / 2.4f)),
+                       expf (logf (x[2]) * (1.0f / 2.4f)),
+                       expf (logf (x[1]) * (1.0f / 2.4f)),
+                       expf (logf (x[0]) * (1.0f / 2.4f)));
+  }
   y = sse_init_newton (x, -1./12, 0.9976800269, 0.9885126933, 0.5908575383);
   x = _mm_sqrt_ps (x);
   /* newton's method for x^(-1/6) */
@@ -262,6 +285,13 @@ static inline __v4sf
 sse_pow_24 (__v4sf x)
 {
   __v4sf y, z;
+  if (sse_max_component (x) > 16.0f) {
+    /* for large values, fall back to a slower but more accurate version */
+    return _mm_set_ps (expf (logf (x[3]) * 2.4f),
+                       expf (logf (x[2]) * 2.4f),
+                       expf (logf (x[1]) * 2.4f),
+                       expf (logf (x[0]) * 2.4f));
+  }
   y = sse_init_newton (x, -1./5, 0.9953189663, 0.9594345146, 0.6742970332);
   /* newton's method for x^(-1/5) */
   z = splat4f (1.f/5.f) * x;